﻿using OF.Lib.DataAccess.Entity;
using OF.Lib.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace OF.Lib.DataAccess.Core
{
    public static class SqlBuilderFactory
    {
        /// <summary>
        /// 获取脚本生成器
        /// </summary>
        /// <param name="connKey"></param>
        /// <returns></returns>
        private static ISqlBuilder GetSqlBuilder(string dbType)
        {
            switch (dbType.Trim().ToUpper())
            {
                case "SQLSERVER":
                    return new SqlBuilderSqlServerImpl(); 
                case "MYSQL":
                    return new SqlBuilderMysqlImpl();
                case "ORACLE":
                    return new SqlBuilderOracleImpl();
                default:
                    throw new Exception(string.Format("[GetSqlBuilder-not support]OF.Lib.DataAccess support only sqlserver,sqllite,mysql,oracle, this \"{0}\" dbtype can not support! ", dbType));
            }

        }

        public static string BuildPagedQuerySql(string sqlKey, QueryFilter filter)
        {
            SQL sqlConfig = SQLConfigHelper.GetSQL(sqlKey);
            DBGroup groupConfig = DBConfigHelper.GetDBGroup(sqlConfig.ConnKey);
            ISqlBuilder sqlBuilder = GetSqlBuilder(groupConfig.DBType);
            return sqlBuilder.BuildPagedQuerySql(sqlConfig, filter);
        }

        public static string BuildSOInsertSql<T>(string dbType, string dbName, object dataParameter, string excludeProperties = null) where T : class, new()
        {
            ISqlBuilder sqlBuilder = GetSqlBuilder(dbType);
            string sql = sqlBuilder.BuildSO_InsertSql<T>(dbName, dataParameter, excludeProperties);
            return sql;

        }
        public static string BuildSOInsertSqlWithReturnPK<T>(string dbType, string dbName, object dataParameter, string excludeProperties = null) where T : class, new()
        {
            ISqlBuilder sqlBuilder = GetSqlBuilder(dbType);
            string sql = sqlBuilder.BuildSO_InsertSqlWithReturnPK<T>(dbName, dataParameter, excludeProperties);
            return sql;

        }

        public static string BuildSOLoad<T>(string dbType, string dbName, Expression<Func<T, bool>> whereMatch, out dynamic paramObject) where T : class, new()
        {
            string table = typeof(T).Name;
            SOWhereBuilder<T> wb = new SOWhereBuilder<T>(dbType);
            wb.Build(whereMatch.Body);
            paramObject = wb.ParameterObject;

            string strWhere = "1=1";
            if (!string.IsNullOrWhiteSpace(wb.Condition))
            {
                strWhere = wb.Condition;
            }
            ISqlBuilder sqlBuilder = GetSqlBuilder(dbType);
            string sql = sqlBuilder.BuildSO_Load(dbName, table, strWhere);
            return sql;
        }

        public static string BuildSOGetList<T>(string dbType, int? top, string dbName, Expression<Func<T, bool>> whereMatch, string orderBy, out dynamic paramObject) where T : class, new()
        {
            string table = typeof(T).Name;
            SOWhereBuilder<T> wb = new SOWhereBuilder<T>(dbType);
            wb.Build(whereMatch.Body);
            paramObject = wb.ParameterObject;

            string strWhere = "1=1";
            if (!string.IsNullOrWhiteSpace(wb.Condition))
            {
                strWhere = wb.Condition;
            }
            ISqlBuilder sqlBuilder = GetSqlBuilder(dbType);
            string sql = sqlBuilder.BuildSO_GetList(top, dbName, table, strWhere, orderBy);
            return sql;
        }

        public static string BuildSOUpdateSql<T>(string dbType, string dbName, object dataParameter, string excludeProperties, Expression<Func<T, bool>> whereMatch, out dynamic paramObject) where T : class, new()
        {
            string table = typeof(T).Name;
            SOWhereBuilder<T> wb = new SOWhereBuilder<T>(dbType);
            wb.Build(whereMatch.Body);
            paramObject = wb.ParameterObject;
            string strWhere = "1=1";
            if (!string.IsNullOrWhiteSpace(wb.Condition))
            {
                strWhere = wb.Condition;
            }

            ISqlBuilder sqlBuilder = GetSqlBuilder(dbType);
            string sql = sqlBuilder.BuildSO_Update( dbName, table,dataParameter, excludeProperties, strWhere, ref paramObject);
            return sql;
        }

        public static string BuildSODelete<T>(string dbType, string dbName,  Expression<Func<T, bool>> whereMatch, out object paramObject) where T : class, new()
        {
            string table = typeof(T).Name;
            SOWhereBuilder<T> wb = new SOWhereBuilder<T>(dbType);
            wb.Build(whereMatch.Body);
            paramObject = wb.ParameterObject;
            string strWhere = "1=1";
            if (!string.IsNullOrWhiteSpace(wb.Condition))
            {
                strWhere = wb.Condition;
            }

            ISqlBuilder sqlBuilder = GetSqlBuilder(dbType);
            string sql = sqlBuilder.BuildSO_Delete(dbName, table,  strWhere);
            return sql;
        }
    }
}
